/*
 * Created on Nov 18, 2003
 */

package com.unash.asn;

/**
 * @author Ashwini Gokhale
 */

import com.unash.util.AsnUtil;
import com.unash.util.Consts;

public class AsnBitString implements Consts{
	
	private final byte[] value;
	private final int size;
	
	/**
	 * @param size Number of bits in this bit string. 
	 * @param value bytearray representation of the bitstring.
	 * @throws IllegalArgumentException
	 * This function initializes size and value. 
	 * And mask the remaining bits with 0. 
	 */
	public AsnBitString(byte[] value,int size) 
	       throws IllegalArgumentException 
	{
		if (ZERO >= size)
			throw new IllegalArgumentException();
		this.size = size;
		this.value = value;
		//Mask the remaining bits with 0
		int byteIndex = (size - ONE) / BYTE_SIZE;
		int bitIndex = size - (byteIndex * BYTE_SIZE) + ONE;
		for(int i= bitIndex; i <= ((byteIndex + ONE) * BYTE_SIZE); i++){
			value[byteIndex] = AsnUtil.maskZero(value[byteIndex],i);	
		}//for		
	} //AsnBitString(int size,byte[] value)

	
	public boolean equals(Object obj) {
		if (!(obj instanceof AsnBitString))
			return false;
		AsnBitString objAsnBitString = (AsnBitString) obj;
		if (this.getSize() != objAsnBitString.getSize())
			return false;
		for (int i = ZERO; i < this.getValue().length; i++) {
			if (this.getValue()[i] != objAsnBitString.getValue()[i])
				return false;
		} //for
		return true;
	} //equals

	
	public int hashCode() {
		int result = 17;
				
		for(int i=ZERO;i<this.getValue().length;i++){
			result = 37 * result + getValue()[i]; 
		}//for
		return result;
	} //hashCode
	
	
	/**
	 * 
	 * @param index ranging from 1 to size of bitString.
	 * @return true if bit = 1
	 * @throws IllegalArgumentException
	 * This function checks whether the specified bit is set to 1.
	 */
	public boolean isBitSet(int index)
		throws IllegalArgumentException
	{
		if((ZERO >= index) || (getSize() < index))
			throw new IllegalArgumentException();
				  
		//get the index in the byte array
		int byteIndex = (index - ONE)/BYTE_SIZE;
		
		//find the distance for shifting value to right
		int noBitRShift = (byteIndex + ONE) * BYTE_SIZE - index;
		
		//RightShift
		int rShiftValue = getValue()[byteIndex] >> noBitRShift;
			
		return((rShiftValue & MASK) == ONE);
	}//getBit
	
	
	public String toString(){
		StringBuffer bitString = new StringBuffer();
		int cnt;
		cnt = getSize() % BYTE_SIZE;
		for(int i=ZERO;i<getValue().length;i++){
			for(int j=1;j<=BYTE_SIZE;j++){
				if(AsnUtil.isBitSet(getValue()[i],j))
					bitString.append(STR_ONE);
				else
					bitString.append(STR_ZERO);
					
				if(i==(getValue().length - ONE) && (j == cnt))
					break;
			}
		}
		return bitString.toString();
	}//toString()
	
	
	/**
	 * This function returns the number of unused bits in the bitString
	 * @return Number of unused bits
	 */
	public int getUnusedBits(){
		return BYTE_SIZE - getSize() % BYTE_SIZE;
	}//getUnusedBits


	

	byte[] getValue() {
		return value;
	}

	int getSize() {
		return size;
	}

	
} //AsnBitString